package com.example.service;

import cn.hutool.core.date.DateUtil;
import com.example.entity.Booking;
import com.example.entity.Room;
import com.example.exception.CustomException;
import com.example.mapper.BookingMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;

@Service
public class BookingService {

    @Resource
    private BookingMapper bookingMapper;  // 依赖注入BookingMapper

    @Resource
    private RoomService roomService;  // 假设RoomService已正确实现

    @Resource
    private RoomAllocationService roomAllocationService;

    @Resource
    private RoomAvailabilityService roomAvailabilityService;

    @Resource
    private NotificationService notificationService;

    public void add(Booking booking) {
        // 新增：校验userId非空
        if (booking.getUserId() == null) {
            throw new CustomException("400", "用户ID不能为空");
        }
        bookingMapper.insert(booking);
    }
        
    public void update(Booking booking) {
        bookingMapper.updateById(booking);
        
        // 如果是状态变更，发送状态变化通知
        if (booking.getStatus() != null) {
            notificationService.sendBookingStatusChangedNotification(booking);
        }
    }

    public void deleteById(Long id) {
        bookingMapper.deleteById(id);
    }

    public void deleteBatch(List<Long> ids) {
        for (Long id : ids) {
            this.deleteById(id);
        }
    }

    public Booking selectById(Long id) {
        return bookingMapper.selectById(id);
    }

    public List<Booking> selectAll(Booking booking) {
        return bookingMapper.selectAll(booking);
    }

    public PageInfo<Booking> selectPage(Booking booking, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<Booking> list = bookingMapper.selectAll(booking);
        return PageInfo.of(list);
    }

    public List<Booking> selectByUserId(Long userId) {
        return bookingMapper.selectByUserId(userId);
    }

    public boolean checkRoomAvailability(Long roomId, String checkInDate, String checkOutDate) {
        return roomAvailabilityService.checkRoomAvailability(roomId, checkInDate, checkOutDate);
    }

    public Booking createBooking(Booking booking) {
        // 日期校验逻辑（保持不变）
        String checkInDateStr = booking.getCheckInDate();
        String checkOutDateStr = booking.getCheckOutDate();
        Date checkInDate = DateUtil.parse(checkInDateStr, "yyyy-MM-dd");
        Date checkOutDate = DateUtil.parse(checkOutDateStr, "yyyy-MM-dd");
        if (checkInDate.compareTo(checkOutDate) >= 0) {
            throw new CustomException("500", "退房日期必须晚于入住日期");
        }

        // 设置默认状态和预订时间
        if (booking.getStatus() == null) {
            booking.setStatus("RESERVED");
        }
        booking.setBookingDate(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));

        // 使用房间分配服务分配最合适的房间
        Room allocatedRoom = null;
        if (booking.getRoomId() == null && roomAllocationService != null) {
            // 如果未指定房间ID，通过智能算法分配房间
            allocatedRoom = roomAllocationService.allocateRoom(booking);
        } else {
            // 指定了房间ID，或没有房间分配服务，进行房间可用性校验
            if (!roomAvailabilityService.checkRoomAvailability(booking.getRoomId(), checkInDateStr, checkOutDateStr)) {
                throw new CustomException("500", "该房间在选定日期内已被预订");
            }
            
            // 获取房间信息
            allocatedRoom = roomService.selectById(booking.getRoomId());
            
            // 更新房间可用数量
            if (allocatedRoom != null && allocatedRoom.getQuantity() > 0) {
                allocatedRoom.setQuantity(allocatedRoom.getQuantity() - 1);
                roomService.update(allocatedRoom);
            } else {
                throw new CustomException("500", "房间不存在或已无可用数量");
            }
        }

        // 计算总价
        long days = ChronoUnit.DAYS.between(checkInDate.toInstant(), checkOutDate.toInstant());
        booking.setTotalPrice(allocatedRoom.getPrice().multiply(BigDecimal.valueOf(days)).doubleValue());

        bookingMapper.insert(booking);
        
        // 发送预订创建通知
        notificationService.sendBookingCreatedNotification(booking);
        
        return booking;
    }
}